package javaz.annotation;

import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

@SuppressWarnings({ "unchecked", "rawtypes", "unused" })
public class MyCustomAnnotation {

	public static void main(String[] args) {
		// viewClassAnnotationFirst();
		// viewClassAnnotationSecond();

		// viewMethodAnnotationFirst();
		// viewMethodAnnotationSecond();

		// viewParamAnnotation();

		// viewFieldAnnotationFirst();
		viewFieldAnnotationSecond();
	}

	@CustomAnnotation(value = "Class annotation")
	class MyClass {

		@CustomAnnotation(value = "Field annotation")
		public String name;

		@CustomAnnotation(value = "Method annotation")
		public void MyMethod() {
		}

		public void ParamMethod(
				@CustomAnnotation(value = "Param annotation") String param) {
		}

	}

	@Retention(RetentionPolicy.RUNTIME)
	public @interface CustomAnnotation {
		String value();
	}

	private static void viewFieldAnnotationSecond() {
		try {
			Field field = MyClass.class.getField("name");
			Annotation annotation = field.getAnnotation(CustomAnnotation.class);

			if (annotation instanceof CustomAnnotation) {
				CustomAnnotation myAnnotation = (CustomAnnotation) annotation;
				System.out.println("value: " + myAnnotation.value());
			}
		} catch (NoSuchFieldException | SecurityException e) {
			e.printStackTrace();
		}
	}

	private static void viewFieldAnnotationFirst() {
		try {
			Field field = MyClass.class.getField("name");
			Annotation[] annotations = field.getDeclaredAnnotations();

			for (Annotation annotation : annotations) {
				if (annotation instanceof CustomAnnotation) {
					CustomAnnotation myAnnotation = (CustomAnnotation) annotation;
					System.out.println("value: " + myAnnotation.value());
				}
			}
		} catch (NoSuchFieldException | SecurityException e) {
			e.printStackTrace();
		}
	}

	private static void viewParamAnnotation() {
		try {
			Method method = MyClass.class
					.getMethod("ParamMethod", String.class);
			Annotation[][] parameterAnnotations = method
					.getParameterAnnotations();
			Class[] parameterTypes = method.getParameterTypes();

			int i = 0;
			for (Annotation[] annotations : parameterAnnotations) {
				Class parameterType = parameterTypes[i++];

				for (Annotation annotation : annotations) {
					if (annotation instanceof CustomAnnotation) {
						CustomAnnotation myAnnotation = (CustomAnnotation) annotation;
						System.out.println("param: " + parameterType.getName());
						System.out.println("value: " + myAnnotation.value());
					}
				}
			}
		} catch (NoSuchMethodException | SecurityException e) {
			e.printStackTrace();
		}
	}

	private static void viewMethodAnnotationFirst() {
		try {
			Method method = MyClass.class.getMethod("MyMethod");
			Annotation[] annotations = method.getDeclaredAnnotations();

			for (Annotation annotation : annotations) {
				if (annotation instanceof CustomAnnotation) {
					CustomAnnotation myAnnotation = (CustomAnnotation) annotation;
					System.out.println("value: " + myAnnotation.value());
				}
			}
		} catch (NoSuchMethodException | SecurityException e) {
			e.printStackTrace();
		}
	}

	private static void viewMethodAnnotationSecond() {
		try {
			Method method = MyClass.class.getMethod("MyMethod");
			Annotation annotation = method
					.getAnnotation(CustomAnnotation.class);

			if (annotation instanceof CustomAnnotation) {
				CustomAnnotation myAnnotation = (CustomAnnotation) annotation;
				System.out.println("value: " + myAnnotation.value());
			}
		} catch (NoSuchMethodException | SecurityException e) {
			e.printStackTrace();
		}
	}

	private static void viewClassAnnotationFirst() {
		Class aClass = MyClass.class;
		Annotation[] annotations = aClass.getAnnotations();

		for (Annotation annotation : annotations) {
			if (annotation instanceof CustomAnnotation) {
				CustomAnnotation myAnnotation = (CustomAnnotation) annotation;
				System.out.println("value: " + myAnnotation.value());
			}
		}
	}

	private static void viewClassAnnotationSecond() {
		Class aClass = MyClass.class;
		Annotation annotation = aClass.getAnnotation(CustomAnnotation.class);

		if (annotation instanceof CustomAnnotation) {
			CustomAnnotation myAnnotation = (CustomAnnotation) annotation;
			System.out.println("value: " + myAnnotation.value());
		}
	}

}
